package com.ctshk.rpc.airexpress.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.RedisConstants;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.bus.SaleableType;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.AppReq;
import com.ctshk.common.utils.Assert;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.redis.KeyUtil;
import com.ctshk.rpc.airexpress.dto.OrderAirexpressConstants;
import com.ctshk.rpc.airexpress.dto.app.AirportExpressCacheDTO;
import com.ctshk.rpc.airexpress.dto.app.AirportExpressChannelDTO;
import com.ctshk.rpc.airexpress.dto.app.AirportExpressH5DTO;
import com.ctshk.rpc.airexpress.dto.app.AirportExpressPCDTO;
import com.ctshk.rpc.airexpress.dto.app.self.platform.AirportExpressChannelSelfPlatformRuleDTO;
import com.ctshk.rpc.airexpress.entity.*;
import com.ctshk.rpc.airexpress.enums.Channel;
import com.ctshk.rpc.airexpress.mapper.*;
import com.ctshk.rpc.airexpress.req.cache.CacheOpsReq;
import com.ctshk.rpc.airexpress.req.cache.CacheSetReq;
import com.ctshk.rpc.airexpress.service.AirportExpressService;
import com.ctshk.rpc.airexpress.service.IAirportExpressAppService;
import com.ctshk.rpc.system.dto.MainDataFieldDTO;
import com.ctshk.rpc.system.dto.MainDataRowDTO;
import com.ctshk.rpc.system.service.*;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@DubboService
public class AirportExpressAppServiceImpl extends ServiceImpl<AirportExpressMapper, AirportExpress> implements IAirportExpressAppService {
    @Autowired
    private AirportExpressMapper airportExpressMapper;
    @Autowired
    private AirportExpressIncreaseStrategyMapper airportExpressIncreaseStrategyMapper;
    @Autowired
    private AirportExpressIncreaseStrategyDateMapper airportExpressIncreaseStrategyDateMapper;
    @Autowired
    private AirportExpressIncreaseStrategyRuleMapper airportExpressIncreaseStrategyRuleMapper;
    @Autowired
    private AirportExpressChannelOfflineAgentCustomMapper airportExpressChannelOfflineAgentCustomMapper;
    @Autowired
    private AirportExpressChannelOfflineSelfCustomMapper airportExpressChannelOfflineSelfCustomMapper;
    @Autowired
    private AirportExpressChannelOnlineSelfPlatformMapper airportExpressChannelOnlineSelfPlatformMapper;
    @Autowired
    private AirportExpressChannelOnlineThirdPlatformMapper airportExpressChannelOnlineThirdPlatformMapper;
    @Autowired
    private AirportExpressInitializationSettingsMapper airportExpressInitializationSettingsMapper;
    @Autowired
    private AirportExpressInitializationSettingsChannelMapper airportExpressInitializationSettingsChannelMapper;
    @DubboReference
    private ISysDepartmentService sysDepartmentService;
    @DubboReference
    private ISysAgentService sysAgentService;
    @DubboReference
    private ISysUserService sysUserService;
    @DubboReference
    private IMainDataTableService mainDataTableService;
    @DubboReference
    private IMainDataFieldService mainDataRowService;
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
    @Autowired
    RedissonClient redissonClient;

    private static final int USE_CHANNEL_STRATEGY = 1;
    private static final int USE_CHANNEL_INIT = 2;

    public Result<List<AirportExpressChannelDTO>> buildCacheData(List<Long> channelIds, List<Long> productIds) {
        // 构建条件
        List<AirportExpress> airportExpressList = airportExpressMapper.selectList(new QueryWrapper<AirportExpress>().lambda()
                .in(CollectionUtils.isNotEmpty(productIds), AirportExpress::getId, productIds)
                .eq(AirportExpress::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(AirportExpress::getSaleStatus, SaleOnShelfStatusCode.SALE_STATUS_1.getCode())
                .eq(AirportExpress::getOnShelfStatus, SaleOnShelfStatusCode.ON_SHELF_STATUS_1.getCode())
                .select(AirportExpress::getId, AirportExpress::getAdultPrice, AirportExpress::getChildrenPrice, AirportExpress::getTicketTypeNameCn
                        , AirportExpress::getTicketTypeNameEn, AirportExpress::getTicketType, AirportExpress::getTicketValidity
                        , AirportExpress::getBookingInformation));
        // 是否有查询到产品结果集
        if (CollectionUtil.isEmpty(airportExpressList)) {
            return Result.failed(SystemError.AIREXPRESS_50011);
        }

        // 查询产品数据
        LocalDate nowDate = LocalDate.now();
        List<Long> airExpressIds = airportExpressList.stream().map(AirportExpress::getId).collect(Collectors.toList());
        // 查询产品当前日期的策略
        List<AirportExpressIncreaseStrategy> airportExpressIncreaseStrategies = airportExpressIncreaseStrategyMapper.selectByAirportExpressIdsNowDate(airExpressIds, nowDate.toString());
        List<AirportExpressChannelSelfPlatformRuleDTO> airportExpressChannelSelfPlatformRuleDTOS = new ArrayList<>();
        HashMap<Long, Integer> channelMap = new HashMap<>();
        // 查询初始化配置, 构建渠道列表
        AirportExpressInitializationSettings airportExpressInitializationSettings = airportExpressInitializationSettingsMapper.selectCheckSetting(Channel.PLATFORM.getId());
        if (airportExpressInitializationSettings != null) {
            List<MainDataRowDTO> mainDataRowDTOS = mainDataTableService.queryData(MainDataTableEnum.OFFICIAL_PLATFORM.getId());
            mainDataRowDTOS.stream().map(o -> o.getList().get(0).getId()).forEach(channelId -> {
                channelMap.put(channelId, USE_CHANNEL_INIT);
            });
        }
        if (CollectionUtils.isNotEmpty(airportExpressIncreaseStrategies)) {
            List<Long> strategyIds = airportExpressIncreaseStrategies.stream().map(AirportExpressIncreaseStrategy::getId).collect(Collectors.toList());
            // 查询自营官方平台策略-加幅规则
            airportExpressChannelSelfPlatformRuleDTOS = airportExpressChannelOnlineSelfPlatformMapper.selectByStrategyIds(strategyIds);
            // 查出加幅规则中，使用了的渠道ID
            if (CollectionUtils.isEmpty(channelIds)) {
                airportExpressChannelSelfPlatformRuleDTOS.stream().forEach(o -> {
                    channelMap.put(o.getChannelId(), USE_CHANNEL_STRATEGY);
                });
            }
        }

        List<AirportExpressChannelDTO> airportExpressChannelDTOList = new ArrayList<>();
        LocalDate localDate = LocalDate.now();
        Iterator<Map.Entry<Long, Integer>> iterator = channelMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, Integer> next = iterator.next();
            Long channelId = next.getKey();
            AirportExpressChannelDTO airportExpressChannelDTO = new AirportExpressChannelDTO();
            airportExpressChannelDTOList.add(airportExpressChannelDTO);
            airportExpressChannelDTO.setChannelId(channelId);
            airportExpressChannelDTO.setAirportExpressList(new ArrayList<>());

            for (AirportExpress airportExpress : airportExpressList) { // 构建渠道-预订列表
                AirportExpressCacheDTO airportExpressCacheDTO = EntityUtil.copy(airportExpress, AirportExpressCacheDTO.class);
                // 查询机场快线-当前日期加幅策略
                AirportExpressIncreaseStrategyRule aeIncreaseStrategyRule = null;
                if (next.getValue() == USE_CHANNEL_STRATEGY) {
                    for (AirportExpressIncreaseStrategy strategy : airportExpressIncreaseStrategies) {
                        if (Objects.equals(airportExpress.getId(), strategy.getAirportExpressId())) {
                            for (AirportExpressChannelSelfPlatformRuleDTO selfPlatformRuleDTO : airportExpressChannelSelfPlatformRuleDTOS) {
                                if (Objects.equals(strategy.getId(), selfPlatformRuleDTO.getIncreaseStrategyId()) && Objects.equals(channelId, selfPlatformRuleDTO.getChannelId())) {
                                    aeIncreaseStrategyRule = EntityUtil.copy(selfPlatformRuleDTO, AirportExpressIncreaseStrategyRule.class);
                                    airportExpressCacheDTO.setRemainderNumber(buildRemainderNumber(aeIncreaseStrategyRule));
                                    break;
                                }
                            }
                        }
                    }
                } else {
                    aeIncreaseStrategyRule = EntityUtil.copy(airportExpressInitializationSettings, AirportExpressIncreaseStrategyRule.class);
                    // 默认售票数量无限制
                    aeIncreaseStrategyRule.setSaleableType(SaleableType.SALEABLE_TYPE_1.getCode());
                }
                if (aeIncreaseStrategyRule != null) {
                    HashMap<Integer, BigDecimal> hashMap = AirportExpressService.buildIncreasePrice(airportExpress, aeIncreaseStrategyRule, Channel.THIRD_PLATFORM.getId());
                    airportExpressCacheDTO.setAdultPrice(hashMap.get(0));
                    airportExpressCacheDTO.setChildrenPrice(hashMap.get(1));
                    airportExpressCacheDTO.setSaleableType(aeIncreaseStrategyRule.getSaleableType());
                    airportExpressCacheDTO.setTicketValidityDate(localDate.plusDays(airportExpress.getTicketValidity()).toString());
                    airportExpressChannelDTO.getAirportExpressList().add(airportExpressCacheDTO);
                }
            }
        }
        return Result.success(airportExpressChannelDTOList);
    }

    @Override
    public Result cacheInit() {
        return cacheInit(null);
    }

    /**
     * 使用渠道id初始化机场快线缓存
     *
     * @param channelIds
     * @return
     */
    @Override
    public Result cacheInit(List<Long> channelIds) {
        // 清理老缓存
        cacheDelete();
        // 查询持久层数据
        Result<List<AirportExpressChannelDTO>> listResult = buildCacheData(channelIds, null);
        // 初始化缓存
        Map<String, Boolean> resultMap = cacheAdd(listResult.getData());
        return new Result(resultMap);
    }

    /**
     * 机场快线PC首页缓存列表查询
     *
     * @return
     */
    @Override
    public Result<AirportExpressPCDTO> getPCHomeList(Long channelId) {
        log.info("【机场快线APP服务-查询PC首页】channelId:{}", channelId);
        List<AirportExpressCacheDTO> airportExpressHongKongList = new ArrayList<>();
        List<AirportExpressCacheDTO> airportExpressKowLoonList = new ArrayList<>();
        List<AirportExpressCacheDTO> airportExpressTSingYiList = new ArrayList<>();
        List<Object> objects = null;
        try {
            Set<String> keys = redisTemplate.keys(KeyUtil.genLikeKey(RedisConstants.AIR_EXPRESS_HOME, String.valueOf(channelId)));
            objects = redisTemplate.opsForValue().multiGet(keys);
        } catch (Exception e) {
            log.warn("【机场快线APP服务-查询PC首页列表】查询缓存数据异常", e);
        }
        if (CollectionUtils.isNotEmpty(objects)) { // redis中不存在，查询数据库
            for (Object item : objects) {
                AirportExpressCacheDTO airportExpressCacheDTO = JSON.parseObject((String) item, AirportExpressCacheDTO.class);
                if (Arrays.asList(1L, 2L).contains(airportExpressCacheDTO.getId())) {
                    airportExpressHongKongList.add(airportExpressCacheDTO);
                } else if (Arrays.asList(3L, 4L).contains(airportExpressCacheDTO.getId())) {
                    airportExpressKowLoonList.add(airportExpressCacheDTO);
                } else if (Arrays.asList(5L, 6L).contains(airportExpressCacheDTO.getId())) {
                    airportExpressTSingYiList.add(airportExpressCacheDTO);
                }
            }
        } else {
            Result<List<AirportExpressChannelDTO>> listResult = buildCacheData(Arrays.asList(channelId), null);
            if (!listResult.isSuccess()) {
                throw new BusinessException(SystemError.AIREXPRESS_50015);
            }
            List<AirportExpressChannelDTO> channelDTOList = listResult.getData();
            if (CollectionUtils.isEmpty(channelDTOList)) {
                throw new BusinessException(SystemError.AIREXPRESS_50015);
            }
            AirportExpressChannelDTO airportExpressChannelDTO = channelDTOList.get(0);
            List<AirportExpressCacheDTO> airportExpressList = airportExpressChannelDTO.getAirportExpressList();
            for (AirportExpressCacheDTO airportExpressCacheDTO : airportExpressList) {
                if (Arrays.asList(1L, 2L).contains(airportExpressCacheDTO.getId())) {
                    airportExpressHongKongList.add(airportExpressCacheDTO);
                } else if (Arrays.asList(3L, 4L).contains(airportExpressCacheDTO.getId())) {
                    airportExpressKowLoonList.add(airportExpressCacheDTO);
                } else if (Arrays.asList(5L, 6L).contains(airportExpressCacheDTO.getId())) {
                    airportExpressTSingYiList.add(airportExpressCacheDTO);
                }
            }
            /**
             * 异步刷新缓存
             */
            CompletableFuture.runAsync(()->{
                cacheAdd(channelDTOList);
            });
        }
        airportExpressHongKongList = airportExpressHongKongList.stream().sorted(Comparator.comparing(AirportExpressCacheDTO::getId)).collect(Collectors.toList());
        airportExpressKowLoonList = airportExpressKowLoonList.stream().sorted(Comparator.comparing(AirportExpressCacheDTO::getId)).collect(Collectors.toList());
        airportExpressTSingYiList = airportExpressTSingYiList.stream().sorted(Comparator.comparing(AirportExpressCacheDTO::getId)).collect(Collectors.toList());
        AirportExpressPCDTO airportExpressPCDTO = new AirportExpressPCDTO();
        airportExpressPCDTO.setAirportExpressHongKongList(airportExpressHongKongList);
        airportExpressPCDTO.setAirportExpressKowLoonList(airportExpressKowLoonList);
        airportExpressPCDTO.setAirportExpressTSingYiList(airportExpressTSingYiList);
        return Result.success(airportExpressPCDTO);
    }

    /**
     * 机场快线H5首页缓存列表查询
     *
     * @return
     */
    @Override
    public Result<AirportExpressH5DTO> getH5HomeList(Long channelId) {
        log.info("【机场快线APP服务-查询H5首页】channelId:{}", channelId);
        List<AirportExpressCacheDTO> singleList = new ArrayList<>();
        List<AirportExpressCacheDTO> returnList = new ArrayList<>();

        List<Object> objects = null;
        try {
            Set<String> keys = redisTemplate.keys(KeyUtil.genLikeKey(RedisConstants.AIR_EXPRESS_HOME, String.valueOf(channelId)));
            objects = redisTemplate.opsForValue().multiGet(keys);
        } catch (Exception e) {
            log.warn("【机场快线APP服务-查询H5首页列表】查询缓存数据异常", e);
        }
        if (CollectionUtils.isNotEmpty(objects)) { // redis中不存在，查询数据库
            for (Object obj : objects) {
                AirportExpressCacheDTO airportExpressCacheDTO = JSON.parseObject((String) obj, AirportExpressCacheDTO.class);
                // 构建单程往返
                if (airportExpressCacheDTO.getTicketType().equals(AirOrderTripType.ONE_WAT.getCode())) {
                    singleList.add(airportExpressCacheDTO);
                } else if (airportExpressCacheDTO.getTicketType().equals(AirOrderTripType.RETURN.getCode())) {
                    returnList.add(airportExpressCacheDTO);
                }
            }
        } else {
            log.info("start query db");
            Result<List<AirportExpressChannelDTO>> listResult = buildCacheData(Arrays.asList(channelId), null);
            log.info("end query db");
            if (!listResult.isSuccess()) {
                throw new BusinessException(SystemError.AIREXPRESS_50015);
            }
            List<AirportExpressChannelDTO> channelDTOList = listResult.getData();
            if (CollectionUtils.isEmpty(channelDTOList)) {
                throw new BusinessException(SystemError.AIREXPRESS_50015);
            }
            AirportExpressChannelDTO airportExpressChannelDTO = channelDTOList.get(0);
            List<AirportExpressCacheDTO> airportExpressList = airportExpressChannelDTO.getAirportExpressList();
            for (AirportExpressCacheDTO airportExpressCacheDTO : airportExpressList) {
                // 构建单程往返
                if (airportExpressCacheDTO.getTicketType().equals(AirOrderTripType.ONE_WAT.getCode())) {
                    singleList.add(airportExpressCacheDTO);
                } else if (airportExpressCacheDTO.getTicketType().equals(AirOrderTripType.RETURN.getCode())) {
                    returnList.add(airportExpressCacheDTO);
                }
            }
            /**
             * 异步刷新缓存
             */
            CompletableFuture.runAsync(()->{
                cacheAdd(channelDTOList);
            });
        }
        singleList = singleList.stream().sorted(Comparator.comparing(AirportExpressCacheDTO::getId)).collect(Collectors.toList());
        returnList = returnList.stream().sorted(Comparator.comparing(AirportExpressCacheDTO::getId)).collect(Collectors.toList());
        AirportExpressH5DTO airportExpressH5DTO = new AirportExpressH5DTO();
        airportExpressH5DTO.setAirportExpressSingleList(singleList);
        airportExpressH5DTO.setAirportExpressReturnList(returnList);
        return Result.success(airportExpressH5DTO);
    }

    @Override
    public Result<AirportExpressCacheDTO> getInfo(Long id, AppReq appReq) {
        BoundHashOperations hashOps = redisTemplate.boundHashOps(KeyUtil.genKey(RedisConstants.AIR_EXPRESS_HOME, String.valueOf(appReq.getChannelId())));
        List<AirportExpressCacheDTO> values = (List<AirportExpressCacheDTO>) hashOps.get(String.valueOf(appReq.getChannelId()));
        for (AirportExpressCacheDTO value : values) {
            if (Objects.equals(value.getId(), id)) {
                return Result.success(value);
            }
        }
        return Result.failed(SystemError.SYS_408);
    }

    /**
     * 机场快线首页缓存添加
     *
     * @param productChannelList 渠道id
     * @return
     */
    public Map<String, Boolean> cacheAdd(List<AirportExpressChannelDTO> productChannelList) {
        log.info("【机场快线服务-新增缓存】方法入参, data:{}", productChannelList);
        Map<String, Boolean> resultMap = new HashMap<>();
        for (AirportExpressChannelDTO data : productChannelList) {
            Long channelId = data.getChannelId();
            // 获取渠道对应的产品信息
            List<AirportExpressCacheDTO> airportExpressList = data.getAirportExpressList();
            // 添加进redis
            airportExpressList.forEach(item -> {
                String key = KeyUtil.genKey(RedisConstants.AIR_EXPRESS_HOME, String.valueOf(channelId), String.valueOf(item.getId()));
                redisTemplate.opsForValue().set(key, JSON.toJSONString(item), 8, TimeUnit.HOURS);
                // 添加余票数量缓存
                redisTemplate.opsForValue().set(RedisConstants.AIR_EXPRESS_HOME_REMAINDER_NUMBER + channelId + ":" + item.getId(), item.getRemainderNumber() == null ? 0 : item.getRemainderNumber());
            });
        }
        // 缓存更新时间标记值
        redisTemplate.opsForValue().set(RedisConstants.AIR_EXPRESS_HOME_UPDATE_TIME, JSON.toJSONString(LocalDateTime.now()));
        return resultMap;
    }

    /**
     * 机场快线首页缓存更新
     *
     * @param req 机场快线产品id
     * @return
     */
    @Override
    public Result cacheUpdate(CacheOpsReq req) {
        log.info("【机场快线-更新redis缓存】开始, data:{}", JSON.toJSONString(req));
        // 获取缓存产品列表
        List<AirportExpressChannelDTO> data = buildCacheData(null, req.getIds()).getData();
        // 删除旧缓存
//        cacheDelete(req);
        for (AirportExpressChannelDTO expressChannelDTO : data) {
            for (AirportExpressCacheDTO item : expressChannelDTO.getAirportExpressList()) {
                String key = KeyUtil.genKey(RedisConstants.AIR_EXPRESS_HOME, String.valueOf(expressChannelDTO.getChannelId()), String.valueOf(item.getId()));
                redisTemplate.opsForValue().set(key, JSON.toJSONString(item));
                redisTemplate.opsForValue().set(RedisConstants.AIR_EXPRESS_HOME_REMAINDER_NUMBER + item.getId(), item.getRemainderNumber() == null ? 0 : item.getRemainderNumber());
            }
        }
        log.info("【机场快线-更新redis缓存】结束");
        return Result.success();
    }

    /**
     * 机场快线 - 删除缓存
     * 如果渠道id和产品id都为空，删除整个缓存分区
     * 如果渠道id不为空，产品id位空，删除渠道id下所有缓存
     * 如果渠道id和产品id都不为空，删除渠道id下指定产品id缓存
     *
     * @param req 删除缓存请求对象
     * @return 删除结果
     */
    @Override
    public Result cacheDelete(CacheOpsReq req) {
        // 如果对象或渠道id为空，删除整个机场快线缓存
        Long channelId = req.getChannelId();
        Long data = null;
        try {
            if (channelId == null && CollectionUtils.isEmpty(req.getIds())) {
                return cacheDelete();
            }
            // 如果渠道id不为空，产品id列表为空，删除整个渠道缓存
            if (channelId != null && CollectionUtils.isEmpty(req.getIds())) {
                String key = KeyUtil.genLikeKey(RedisConstants.AIR_EXPRESS_HOME, String.valueOf(channelId));
                Set<String> keys = redisTemplate.keys(key);
                data = redisTemplate.delete(keys);
                return Result.success(data);
            }
            if (channelId == null && CollectionUtils.isNotEmpty(req.getIds())) {
                Set<String> keys = new HashSet<>();
                req.getIds().forEach(productId -> {
                    String key = KeyUtil.genKey(RedisConstants.AIR_EXPRESS_HOME, KeyUtil.LIKE, String.valueOf(productId));
                    keys.addAll(redisTemplate.keys(key));
                });
                data = redisTemplate.delete(keys);
                return Result.success(data);
            }
            // 都不为空，删除指定渠道中的指定产品缓存
            Set<String> keys = new HashSet<>();
            req.getIds().forEach(productId -> {
                keys.add(KeyUtil.genKey(RedisConstants.AIR_EXPRESS_HOME, String.valueOf(channelId), String.valueOf(productId)));
            });
            data = redisTemplate.delete(keys);
        } catch (Exception e) {
            log.error("【机场快线APP-删除产品缓存】异常", e);
        }
        return Result.success(data);
    }

    /**
     * 删除缓存 - all
     *
     * @return
     */
    @Override
    public Result cacheDelete() {
        redisTemplate.delete(RedisConstants.AIR_EXPRESS_HOME);
        redisTemplate.delete(RedisConstants.AIR_EXPRESS_HOME_REMAINDER_NUMBER);
        return Result.success();
    }

    private Map<String, Boolean> hasKeys(BoundHashOperations hashOps, Long channelId, List<Long> productIds) {
        // 查看是否添加成功
        Map<String, Boolean> resultmap = new HashMap<>();
        BoundHashOperations finalHashOps = hashOps;
        if (!CollectionUtil.isEmpty(productIds)) {
            productIds.forEach(id -> {
                Boolean flag = finalHashOps.hasKey(channelId + ":" + id);
                resultmap.put(id.toString(), flag);
            });
        } else {
            Set<String> keys = finalHashOps.keys();
            for (String key : keys) {
                if (key.contains(channelId.toString())) {
                    resultmap.put(key, true);
                }
            }
        }
        return resultmap;
    }

    /**
     * 新增or更新结果判断
     *
     * @param hashOps
     * @param req
     * @return
     */
    private Map<String, Boolean> hasKeys(BoundHashOperations hashOps, CacheOpsReq req) {
        // 查看是否添加成功
        Map<String, Boolean> resultmap = new HashMap<>();
        Long channelId = req.getChannelId();
        BoundHashOperations finalHashOps = hashOps;
        if (!CollectionUtil.isEmpty(req.getIds())) {
            req.getIds().forEach(id -> {
                Boolean flag = finalHashOps.hasKey(channelId + ":" + id);
                resultmap.put(id.toString(), flag);
            });
        } else {
            Set<String> keys = finalHashOps.keys();
            for (String key : keys) {
                if (key.contains(channelId.toString())) {
                    resultmap.put(key, true);
                }
            }
        }
        return resultmap;
    }

    /**
     * 执行hash缓存删除
     *
     * @param hashOps
     * @param keys
     * @return
     */
    private Map<String, Boolean> deleteHash(BoundHashOperations hashOps, List<String> keys) {
        Map<String, Boolean> map = new HashMap<>();
        keys.forEach(key -> {
            Long delete = hashOps.delete(key);
            map.put(key, delete == 1);
        });
        return map;
    }

    /**
     * 执行 K:V 缓存删除
     *
     * @param keys 需要删除的keys
     * @return
     */
    private Map<String, Boolean> deletString(List<String> keys) {
        Map<String, Boolean> map = new HashMap<>();
        keys.forEach(key -> {
            Boolean delete = redisTemplate.delete(key);
            map.put(key, delete);
        });
        return map;
    }

    /**
     * 机场快线 - 剩余票数缓存操作
     *
     * @param req 操作请求对象
     */
    @Override
    public Result remainderNumberCacheOps(CacheSetReq req) {
        String key = RedisConstants.AIR_EXPRESS_HOME_REMAINDER_NUMBER + req.getChannelId() + ":" + req.getKey();
        Boolean hasKey = redisTemplate.hasKey(key);
        // 如果key不存在
        if (!hasKey) {
            return Result.failed(SystemError.AIREXPRESS_50012);
        }
        // 绑定操作key
        BoundValueOperations<String, Object> valueOps = redisTemplate.boundValueOps(key);
        Integer type = req.getType();
        String msg = "操作成功";
        RLock lock = redissonClient.getLock(RedisConstants.AIR_EXPRESS_REMAINDER_NUMBER_LOCK + req.getChannelId() + ":" + req.getKey());
        try {
            lock.lock(30, TimeUnit.SECONDS);
            // 根据操作类型执行操作
            if (RedisOpsStatusCode.ADD.getCode().intValue() == type.intValue()) {
                Long increment = valueOps.increment(req.getVal());
                msg = " 剩余票数为：" + increment;
            } else if (RedisOpsStatusCode.MIN.getCode().intValue() == type.intValue()) {
                Long num = (Long) valueOps.get();
                if (num - req.getVal() >= 0) {
                    Long decrement = valueOps.decrement(req.getVal());
                    msg = " 剩余票数为：" + decrement;
                } else {
                    return Result.failed(SystemError.AIREXPRESS_50013);
                }
            } else if (RedisOpsStatusCode.QUERY.getCode().intValue() == type.intValue()) {
                return Result.success(Long.valueOf(valueOps.get().toString()));
            } else if (RedisOpsStatusCode.SET.getCode().intValue() == type.intValue()) {
                valueOps.set(req.getVal());
            } else if (RedisOpsStatusCode.DEL.getCode().intValue() == type.intValue()) {
                Map<String, Boolean> resultMap = deletString(Arrays.asList(key));
                Set<String> keySet = resultMap.keySet();
                Iterator<String> iterator = keySet.iterator();
                Boolean result = resultMap.get(iterator.next());
                if (!result) {
                    msg = "操作失败";
                }
            }
        } finally {
            lock.unlock();
        }
        return Result.success(msg);
    }

    /**
     * 计算可售数量
     *
     * @param aeIncreaseStrategyRule
     */
    private int buildRemainderNumber(AirportExpressIncreaseStrategyRule aeIncreaseStrategyRule) {
        if (aeIncreaseStrategyRule.getSaleableType() == OrderAirexpressConstants.SALE_TYPE_LIMIT) {
            int saleableNumber = aeIncreaseStrategyRule.getSaleableNumber() == null ? 0 : aeIncreaseStrategyRule.getSaleableNumber();
            int soldNumber = aeIncreaseStrategyRule.getSoldNumber() == null ? 0 : aeIncreaseStrategyRule.getSoldNumber();
            return saleableNumber - soldNumber;
        }
        return 0;
    }

}
